using System.Collections.Generic;
using System.Threading.Tasks;

namespace Nice157Advices.Advices
{
    /// <summary>
    /// 81.使用Parallel 简化同步状态下Task 的使用
    /// 82：Parallel 简化但不等同于Task默认行为
    /// </summary>
    public static class _81_82
    {
        /**
         * 在命名空间System.Threading.Tasks中，有一个静态类Parallel 简化了在同步状态下的Task 的操作。Parallel主要提供3个有用的方法：For、ForEach、Invoke。
         */
        public static void Go ()
        {
            /**
             * 可以看到，工作代码并未按照数组的索引次序进行遍历。这是因为我们的遍历是并行的，不是顺序的。所以，这里也可以引出一个小建议：如果我们的输出必须是同步的或者说必须是顺序输出的，则不应使用Parallel的方式。
             * 
             * 使用For 和ForEach方法，Parallel 类型会自动为我们分配Task来完成针对元素的一些工作。当然我们也可以直接使用Task，但是上面的这种形式在语法上更为简洁。
             */

            // 所有任务是并行的，且是同步的，意味着主线程会被阻滞

            // _For ();
            // _Foreach ();
            _Invoke();
        }

        /// <summary>
        /// For 方法主要用于针对数组的并行操作
        /// </summary>
        private static void _For ()
        {
            int[] nums = new int[] { 1, 2, 3, 4 };
            Parallel.For (0, nums.Length, (i) =>
            {
                System.Console.WriteLine ($"{i}: {nums[i]}");
            });
            System.Console.ReadKey ();
        }

        /// <summary>
        /// Foreach 方法主要用于处理泛型集合元素的并行操作
        /// </summary>
        private static void _Foreach ()
        {
            List<int> nums = new List<int> { 1, 2, 3, 4 };
            Parallel.ForEach (nums, (item) =>
            {
                System.Console.WriteLine ($"{item}");
            });
        }

        /// <summary>
        /// Parallel 的Invoke 方法为我们简化了启动一组并行操作，它隐式启动的就是Task
        /// </summary>
        private static void _Invoke ()
        {
            Parallel.Invoke (() =>
            {
                System.Console.WriteLine ("C");
            }, () =>
            {
                System.Console.WriteLine ("A");
            }, () => System.Console.WriteLine ("P"));
        }
    }
}